package cn.thens.one.net

import android.annotation.SuppressLint
import cn.thens.kdroid.core.KDroid
import com.google.gson.Gson
import io.reactivex.schedulers.Schedulers
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.CallAdapter
import retrofit2.Converter
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import java.io.InputStream
import java.io.OutputStream
import java.security.SecureRandom
import javax.net.ssl.SSLContext
import javax.net.ssl.X509TrustManager
import kotlin.reflect.KClass

abstract class RetrofitProxy {
    abstract val baseUrl: String
    open val converterFactory: Converter.Factory by lazy { GsonConverterFactory.create(Gson()) }
    open val callAdapterFactory: CallAdapter.Factory by lazy { RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()) }

    protected val retrofit: Retrofit by lazy {
        Retrofit.Builder()
                .client(okHttpClientBuilder.build())
                .baseUrl(baseUrl)
                .addConverterFactory(converterFactory)
                .addCallAdapterFactory(callAdapterFactory)
                .build()
    }

    open val okHttpClientBuilder: OkHttpClient.Builder by lazy {
        val sslContext = SSLContext.getInstance("SSL")
        sslContext.init(null, arrayOf(MyTrustManager()), SecureRandom())
        val logLevel = if (KDroid.debug) HttpLoggingInterceptor.Level.BODY else HttpLoggingInterceptor.Level.NONE
        OkHttpClient.Builder()
//                .apply { if (AppOwner.debug) addNetworkInterceptor(StethoInterceptor()) }
                .sslSocketFactory(sslContext.socketFactory)
                .hostnameVerifier { _, _ -> true }
                .addInterceptor(HttpLoggingInterceptor(HttpLogger()).setLevel(logLevel))
    }

    open fun <T : Any> create(clz: KClass<T>): T {
        return retrofit.create(clz.java)
    }

    @SuppressLint("TrustAllX509TrustManager")
    private class MyTrustManager : X509TrustManager {
        override fun checkClientTrusted(chain: Array<out java.security.cert.X509Certificate>?, authType: String?) {
        }

        override fun checkServerTrusted(chain: Array<out java.security.cert.X509Certificate>?, authType: String?) {
        }

        override fun getAcceptedIssuers(): Array<java.security.cert.X509Certificate> {
            return arrayOf()
        }
    }

    private fun copy(inputStream: InputStream, outputStream: OutputStream) {
        inputStream.copyTo(outputStream)
    }
}